package com.wzh.mall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @program: mall
 * @description: CompletableFuture测试类
 * @author: Mr.Wang
 * @create: 2021-09-12 20:49
 **/
public class CompletableFutureTest {

    public static ExecutorService executor= Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main开始了。。。");
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//        }, executor);
        /*
        *
        * 方法完成后的感知处理
        * */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).whenComplete((res,exception)->{
//            // 虽然可以得到异常信息 但是没法修改结果
//            System.out.println("异步任务成功了,结果是："+res+"异常是："+exception);//异步任务成功了,结果是：5异常是：null
//            //异步任务成功了,结果是：null异常是：java.util.concurrent.CompletionException
//        }).exceptionally(throwable -> {
//            // 感知异常 同时返回默认值（对异常的处理结果）
//            return 10;
//        });
        /*
        *
        * 方法完成后的处理
        * */
//        CompletableFuture<Integer> future  = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).handle((res, thr) -> {
//            if (res != null) {
//                return res * 2;
//            }
//            if (thr != null) {
//                return 0;
//            }
//            return 0;
//        });
        /*
        *
        * 线程串行化
        *   1) thenRun:不能获取到上一步的执行结果 无返回值
        *       .thenRunAsync(()->{
                    System.out.println("任务2启动了。。。");//任务2启动了。。。
                },executor);
        *   2) thenAcceptAsync: 能接受上一步结果 无返回值
        *       .thenAcceptAsync((res)->{
                     System.out.println("任务2启动了。。。"+res);//任务2启动了。。。2
                },executor);
        *   3) thenApplyAsync: 能接受上一步结果 同时有返回值
        *       .thenApplyAsync((res) -> {
                     System.out.println("任务2启动了。。。" + res);//任务2启动了。。。2
                     return "hello" + res;
                }, executor);
                System.out.println(future.get()); //hello2
        * */
//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenApplyAsync((res) -> {
//            System.out.println("任务2启动了。。。" + res);
//            return "hello" + res;
//        }, executor);
//        System.out.println(future.get());
//        Integer integer = future.get(); //链式阻塞等待
//        System.out.println(integer);


        /*
        * 合并两个异步任务
        *   (1) 两个任务必须都完成,触发该任务。
        *
        *       1) thenCombine:组合两个future,获取两个future的返回结果,并返回当前任务的返回值
        *       2) henAcceptBoth:组合两个future,获取两个future任务的返回结果,然后处理任务,没有henhxetsot返回值。
        *       3) runAfterBoth:组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务。
        * */

        // 任务一
//        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务01线程" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("任务01运行结果：" + i);
//            return i;
//        }, executor);
//
//        // 任务二
//        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务02线程" + Thread.currentThread().getId());
//            System.out.println("任务02运行结果：" );
//            return "Hello";
//        }, executor);

        // 任务三 必须是前两个任务执行完才能执行
//        future01.runAfterBothAsync(future02,()->{
//            System.out.println("任务03线程" + Thread.currentThread().getId());
//        },executor);
//        future01.thenAcceptBothAsync(future02,(f1,f2)->{
//            System.out.println("任务03线程" + Thread.currentThread().getId()+"---"+f1+"--"+f2);//任务03线程11---2--Hello
//        },executor);
//        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
//            System.out.println("任务03线程" + Thread.currentThread().getId());
//            return f1 + "--" + f2;
//        }, executor);
//        System.out.println(future.get());//2--Hello

        /*
        *  当两个任务中,任意一个future任务完成的时候,执行任务。
        *       applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。 必须返回值类型相等
        *       acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。 必须返回值类型相等
        *       runAfterEither:两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值。
        * */

//        // 任务一
//        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务01线程" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("任务01运行结果：" + i);
//            return i;
//        }, executor);
//
//        // 任务二
//        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务02线程" + Thread.currentThread().getId());
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("任务02运行结果：" );
//            return "Hello";
//        }, executor);

        // 任务三
//        future01.runAfterEitherAsync(future02,()->{
//            System.out.println("任务03线程" + Thread.currentThread().getId());
//        },executor);
//        System.out.println("main结束了。。。");

//        future01.acceptEitherAsync(future02,(f)->{
//            System.out.println("任务03线程" + Thread.currentThread().getId()+"---"+f);
//        },executor);
//        CompletableFuture<String> future = future01.applyToEitherAsync(future02, (f) -> {
//            System.out.println("任务03线程" + Thread.currentThread().getId() + "---" + f); //任务03线程11---2
//            return "hahaha";
//        }, executor);
//        System.out.println(future.get());//hahaha


        /*
        * 多任务组合：
        *       （1）、
        *       （2）、
        * */
        // 任务一
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(1000);
                System.out.println("这是查询商品图片的。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello.jpg";
        }, executor);
        // 任务二
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(1000);
                System.out.println("这是查询商品属性的。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "黑色+8+126";
        }, executor);
        // 任务三
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(1000);
                System.out.println("这是查询商品介绍的。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "华为";
        },executor);

        // 原始阻塞式：
//        futureImg.get();
//        futureAttr.get();
//        futureDesc.get();
        // allOf() 三个都做完执行方法
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureDesc, futureAttr);
//        System.out.println(allOf.get());//hello.jpg黑色+8+126华为
//        allOf.get(); //阻塞 等待三个执行完
        // anyof() 三个只要有一个执行完
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureDesc, futureAttr);
        System.out.println(anyOf.get());//华为
        System.out.println("main完成");
    }

}
